package com.xw.unification.entity.request;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class ServletInputStreamWrapper extends ServletInputStream {

    private ReadListener listener;
    private int length;
    private final ByteArrayInputStream input;
    static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    public ServletInputStreamWrapper(RepeatableHttpServletRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("HttpServletRequest can not be null");
        }
        ServletInputStream input = null;
        if (request instanceof CopyOnReadHttpServletRequest) {
            byte[] data = ((CopyOnReadHttpServletRequest) request).getData();
            if (data == null) {
                this.length = 0;
                this.input = new ByteArrayInputStream(new byte[] {});
            } else {
                this.length = data.length;
                this.input = new ByteArrayInputStream(data);
            }
        } else {
            this.input = null;
        }
    }

    @Override
    public boolean isFinished() {
        return length > 0;
    }

    @Override
    public boolean isReady() {
        if (listener != null) {
            try {
                listener.onDataAvailable();
            } catch (IOException e) {
                listener.onError(e);
            }
        }
        return isFinished();
    }

    @Override
    public void setReadListener(ReadListener readListener) {
        this.listener = readListener;
        if (!isFinished()) {
            try {
                readListener.onDataAvailable();
            } catch (IOException e) {
                readListener.onError(e);
            }
        } else {
            try {
                readListener.onAllDataRead();
            } catch (IOException e) {
                readListener.onError(e);
            }
        }
    }

    @Override
    public int read() throws IOException {
        if (length <= 0) {
            if (listener != null) {
                try {
                    listener.onAllDataRead();
                } catch (IOException ex) {
                    listener.onError(ex);
                    throw ex;
                }
            }
            return -1;
        }
        int i = input.read();
        if (i >= 0) {
            length--;
            return i;
        } else {
            length = 0;
            if (listener != null) {
                try {
                    listener.onAllDataRead();
                } catch (IOException ex) {
                    listener.onError(ex);
                    throw ex;
                }
            }
            return -1;
        }
    }

}
